#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/timerfd.h>

int main()
{
    // int timerfd_create(int clockid, int flags);
    // 1. 创建定时器对象
    int timerfd = timerfd_create(CLOCK_MONOTONIC, 0);
    if (timerfd < 0)
    {
        perror("timerfd_create error");
        exit(1);
    }

    // 设置首次超时时间
    struct itimerspec itime;
    itime.it_value.tv_sec = 2;  // 秒
    itime.it_value.tv_nsec = 0; // 纳秒

    // 设置超时之后每间隔多久再次触发
    itime.it_interval.tv_sec = 2;
    itime.it_interval.tv_nsec = 0;

    // int timerfd_settime(int fd, int flags, const struct itimerspec *new_value, struct itimerspec *old_value);
    // 2. 启动定时器
    int n = timerfd_settime(timerfd, 0, &itime, NULL);
    if (n == -1)
    {
        perror("timerfd_settime error");
        exit(2);
    }

    // 根据上面所设参数，2s之后OS会向timerfd写入1次超时次数，如果不读走这个1，以后每隔2s就再次写入2，表示超时次数是2了
    // 当我们读走了数据后，下一次就重新写入超时次数

    sleep(4);

    // 一次要读取8字节的数据
    uint64_t times;
    n = read(timerfd, &times, 8);
    if (n < 0)
    {
        perror("read error");
        exit(3);
    }
    printf("超时次数: %d\n", times);    // 上面sleep(4)，所以读到2


    // 由于read是阻塞读的，当执行到这里时，read会等到timerfd有数据，读到times才返回
    n = read(timerfd, &times, 8);
    if (n < 0)
    {
        perror("read error");
        exit(3);
    }
    printf("超时次数: %d\n", times);    // 1

    close(timerfd);
    return 0;
}